<!--
 * @Description: 
 * @Author: shizhe
 * @Date: 2022-03-23 16:27:04
 * @LastEditTime: 2022-07-04 12:46:23
 * @LastEditors: shizhe
 * @Reference: 
-->
<template>
  <div id="edit">
    <el-upload
      action="#"
      ref="annexUpload"
      :headers="loadHeader"
      accept=".jpg,.png,.jpeg"
      :show-file-list="false"
      :http-request="handleRequest"
      multiple
      drag
      :before-upload="beforeUpload"
      :on-success="uploadSuccess"
      :file-list="uploadList"
    >
      <div ref="upload"></div>
    </el-upload>
    <quill-editor v-model="value" :options="editorOption" ref="myQuillEditor"></quill-editor>
  </div>
</template>

<script>
import { quillEditor, Quill } from 'vue-quill-editor'
import { container, ImageExtend, QuillWatch } from 'quill-image-extend-module'

Quill.register('modules/ImageExtend', ImageExtend)
export default {
  props: {
    option: {},
    infoValue: {
      type: String
    }
  },
  data() {
    return {
      // 富文本实例
      quill: null,

      num: 0,
      num2: 0,
      num3: 0,
      timer: null,
      fileSuccess: true,
      fileCopyUpload: true,
      filedropUpload: true,
      uploadList: [],
      value: '',
      length: 0,
      editorOption: {
        placeholder: '请输入信息或插入图片',
        modules: {
          // ImageExtend: {
          //   loading: true,
          //   name: 'file',
          //   size: 10, // 可选参数 图片大小，单位为M，1M = 1024kb
          //   action: this.GLOBAL.weburl + '/api/file/upload', // 服务器地址, 如果action为空，则采用base64插入图片
          //   response: res => {
          //     return res.data
          //   },
          //   headers: xhr => {
          //
          //   }, // 可选参数 设置请求头部
          //   sizeError: () => {
          //     this.$message.error('图片超出大小')
          //     return
          //   }, // 图片超过大小的回调
          //   start: file => {
          //     console.log(file)
          //   }, // 可选参数 自定义开始上传触发事件
          //   end: () => {}, // 可选参数 自定义上传结束触发的事件，无论成功或者失败
          //   error: () => {}, // 可选参数 上传失败触发的事件
          //   success: () => {}, // 可选参数  上传成功触发的事件
          //   change: (xhr, formData) => {
          //     // console.log(xhr)
          //     // xhr.setRequestHeader('myHeader','myValue')
          //     // formData.append('token', 'myToken')
          //   } // 可选参数 每次选择图片触发，也可用来设置头部，但比headers多了一个参数，可设置formData
          // },
          toolbar: {
            container: this.option || container, // container为工具栏，此次引入了全部工具栏，也可自行配置
            handlers: {
              image: () => {
                // 劫持原来的图片点击按钮事件
                // QuillWatch.emit(this.quill.id)
                // console.log(1)
                this.$refs.upload.click()
              }
            }
          }
        }
      }
    }
  },
  watch: {
    value() {
      if (!this.value) {
        let quillLoading = document.querySelector('.quill-loading')
        quillLoading && quillLoading.remove()
      }
    },
    infoValue() {
      this.value = this.infoValue
    }
  },
  components: { quillEditor },
  mounted() {
    // //  自定义粘贴图片功能
    this.quill = this.$refs.myQuillEditor.quill

    // 监听拖拽事件
    this.quill.root.addEventListener('dragover', function (e) {
      e.preventDefault()
      e.stopPropagation()
    })
    this.quill.root.addEventListener('dragenter', function (e) {
      e.preventDefault()
      e.stopPropagation()
    })
    this.quill.root.addEventListener('drop', e => {
      // 必须要禁用浏览器默认事件
      if (e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files.length) {
        e.preventDefault()
        e.stopPropagation()
        const fileList = e.dataTransfer.files
        ;[].forEach.call(e.dataTransfer.files, file => {
          this.num3++
          this.filedropUpload = false
          if (!file.type.match(/^image\/(jpe?g|a?png|bmp)/i)) {
            this.$message.error('请确认拖拽上传的是否为静态图片')
            return
          }

          this.uploadToServer(file, fileList, res => {
            // 获取光标内容
            this.uploadAttachment(res, file, fileList)
            let range = this.quill.getSelection()
            if (this.num3 == fileList.length) {
              this.filedropUpload = true
              this.num3 = 0
            }
            if (range) {
              //  将光标移动到图片后面
              this.$refs.myQuillEditor.quill.setSelection(range.index + 1)
            }
          })
        })
      }
    })

    // 监听粘贴上传事件
    this.quill.root.addEventListener(
      'paste',
      evt => {
        if (evt.clipboardData && evt.clipboardData.files && evt.clipboardData.files.length) {
          evt.preventDefault()
          const fileList = evt.clipboardData.files
          ;[].forEach.call(evt.clipboardData.files, file => {
            this.num2++
            this.fileCopyUpload = false
            if (!file.type.match(/^image\/(jpe?g|a?png|bmp)/i)) {
              this.$message.error('请确认复制粘贴的是否为静态图片')
              return
            }

            this.uploadToServer(file, fileList, res => {
              // 获取光标内容
              this.uploadAttachment(res, file, fileList)
              let range = this.quill.getSelection()
              if (this.num2 == fileList.length) {
                this.fileCopyUpload = true
                this.num2 = 0
              }
              if (range) {
                //  将光标移动到图片后面
                this.$refs.myQuillEditor.quill.setSelection(range.index + 1)
              }
            })
          })
        }
      },
      false
    )
  },
  methods: {
    handleRequest(file) {
      this.uploadToServer(file, null, null)
    },
    // 上传图片
    uploadToServer(file, fileList, cb) {
      const that = this
      let isLt = file.size / 1024 / 1024 / 10 <= 1
      if (!cb) {
        isLt = file.file.size / 1024 / 1024 / 10 <= 1
      }

      if (!isLt) {
        this.$message.error('单个文件大小不能超过10M,请检查文件大小并重新尝试')
        return
      }

      // 创建loding盒子
      let quillLoading = document.querySelector('.quill-loading')
      if (quillLoading === null) {
        quillLoading = document.createElement('div')
        quillLoading.classList.add('quill-loading')
        quillLoading.classList.add('extend-upload-success')
        document.querySelector('.ql-container').appendChild(quillLoading)
      }
      // 上传之前记录length
      this.length = this.quill.getSelection().index
      console.log(this.length)
      if (!this.value) {
        this.length = 0
      }

      let xhr = new XMLHttpRequest()
      let formData = new FormData()
      formData.append('file', file)
      if (!cb) {
        formData.append('file', file.file)
      }

      xhr.open('post', this.GLOBAL.weburl + '/api/file/upload')
      xhr.setRequestHeader(this.GLOBAL.tokenName, this.common.getCookie('materialsToken'))
      xhr.withCredentials = true
      xhr.responseType = 'json'
      // 开始上传数据
      xhr.upload.onloadstart = function (e) {
        let length = (that.quill.getSelection() || {}).index || that.quill.getLength()
        that.quill.insertText(length, '[uploading...]', { color: 'red' }, true)
        quillLoading.classList.remove('extend-upload-success')
      }
      // 上传过程
      xhr.upload.onprogress = function (e) {
        let complete = (((e.loaded / e.total) * 100) | 0) + '%'
        quillLoading.innerHTML = '已上传' + complete
      }
      // 当发生网络异常的时候会触发，如果上传数据的过程还未结束
      xhr.upload.onerror = function (e) {
        that.quill.root.innerHTML = that.quill.root.innerHTML.replace('[uploading...]', '[upload error]')

        that.quillLoading.classList.add('extend-upload-warning-color')
        quillLoading.innerHTML = '网络异常，失败请重试'
        setTimeout(function () {
          that.quillLoading.classList.remove('extend-upload-warning-color')
          quillLoading.classList.add('extend-upload-success')
        }, 1500)
      }
      xhr.send(formData)
      xhr.onload = () => {
        setTimeout(function () {
          quillLoading.classList.add('extend-upload-success')
        }, 1000)

        if (xhr.readyState === 4 && xhr.status === 200) {
          this.quill.root.innerHTML = this.quill.root.innerHTML.replace('[uploading...]', '')
          // 判断是粘贴，拖拽上传还是选择图片上传
          if (cb) {
            cb(xhr.response)
          } else {
            file.onSuccess(xhr.response)
          }
        } else {
          this.quill.root.innerHTML = this.quill.root.innerHTML.replace('[uploading...]', '[upload error]')
        }
      }
    },
    uploadAttachment(response, file, fileList) {
      // 保存文件信息
      if (response.code === 0) {
        // 获取富文本组件实例
        let quill = this.$refs.myQuillEditor.quill
        // 插入图片  res.info为服务器返回的图片地址
        quill.insertEmbed(this.length, 'image', response.data)
        quill.setSelection(this.length)
      } else {
        this.$message.error(response.msg)
      }
      // 清空文件列表
      this.uploadList = []
    },
    // 文件上传前进行文件大小检测
    beforeUpload(file) {
      this.fileSuccess = false
      const isLt = file.size / 1024 / 1024 / 10 <= 1
      if (!isLt) {
        this.$message.error('单个文件大小不能超过10M,请检查文件大小并重新尝试')
      }
      return isLt
    },

    // 上传成功时的回调
    uploadSuccess(val, e, el) {
      if (e.response.code != 0) {
        this.$message.error(e.response.msg)
        return false
      }
      this.num++
      if (this.num == el.length) {
        this.num = 0
        this.fileSuccess = true
      }
      clearTimeout(this.timer)
      this.timer = setTimeout(() => {
        this.$message.success('上传成功')
      }, 500)
      this.uploadAttachment(e.response, e, el)
      // 获取光标内容
      let range = this.quill.getSelection()
      if (range) {
        //  将光标移动到图片后面
        // console.log(range.index)
        this.quill.setSelection(range.index + 1)
      }

      this.uploadList = el
    }
  },
  computed: {
    loadHeader() {
      let token = this.common.getCookie('materialsToken')
      const header = {}
      header[this.GLOBAL.tokenName] = token
      return header
    }
  }
}
</script>
<style lang="less" scoped>
#edit {
  /deep/ .ql-editor {
    min-height: 300px;
    max-height: 365px;
    overflow-y: auto;
  }
  /deep/ .el-upload {
    display: none;
  }
}
</style>
